#ifndef _MD5_HASHING_
#define _MD5_HASHING_

#include <stdint.h>
#include "HashingStrategy.hpp"


class MD5hashing : public HashingStrategy {

    private:

        //static const unsigned int _SIZE = 16;
        static const uint8_t _PADDING[64];

        // contexte
        uint32_t state[4];        /* state (ABCD) */
        uint32_t count[2];        /* number of bits, modulo 2^64 (lsb first) */
        uint8_t buffer[64];       /* input buffer */

        void transform( const uint8_t block[64] );
        static void encode ( uint8_t *output, const uint32_t *input, size_t len );
        static void decode ( uint32_t *output, const uint8_t *input, size_t len );

        static inline uint32_t F( uint32_t x, uint32_t y, uint32_t z );
        static inline uint32_t G( uint32_t x, uint32_t y, uint32_t z );
        static inline uint32_t H( uint32_t x, uint32_t y, uint32_t z );
        static inline uint32_t I( uint32_t x, uint32_t y, uint32_t z );

        static inline void FF( uint32_t &a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, unsigned int s, uint32_t ac );
        static inline void GG( uint32_t &a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, unsigned int s, uint32_t ac );
        static inline void HH( uint32_t &a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, unsigned int s, uint32_t ac );
        static inline void II( uint32_t &a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, unsigned int s, uint32_t ac );

    public:

        MD5hashing( void );
        ~MD5hashing( void );

        void process( const uint8_t *message_array, size_t length );
        void finalize( void );

};

#endif
